﻿using Microsoft.Win32;
using System;
using System.Diagnostics;

namespace Log
{
    public class EventLog
    {
        #region Members

        /// <summary>
        /// Event Log Max Size
        /// </summary>
        private const string m_maxSizeValueName = "MaxSize";
        private const string m_retentionValueName = "Retention";

        /// <summary>
        /// Check Event Log Initialization
        /// </summary>
        private bool m_EventlogConfigurate = false;

        /// <summary>
        /// Framework EventLog
        /// </summary>
        private System.Diagnostics.EventLog m_EventLogFmk = null;

        /// <summary>
        /// Defaut EventLog Name
        /// </summary>
        private string m_EventViewerName = "Application";

        /// <summary>
        /// Default Source Name
        /// </summary>
        private string m_SourceName = "Default";

        /// <summary>
        /// Enable/Disable Log
        /// </summary>
        private bool m_IsDebugEnabled = true;
        private bool m_IsErrorEnabled = true;
        private bool m_IsFailureEnabled = true;
        private bool m_IsInfoEnabled = true;
        private bool m_IsSuccessEnabled = true;
        private bool m_IsWarnEnabled = true;
        #endregion

        #region Event
        /// <summary>
        /// Log Event
        /// </summary>
        public event EventViewerEventHandler DebugEvent;
        public event EventViewerEventHandler ErrorEvent;
        public event EventViewerEventHandler FailureEvent;
        public event EventViewerEventHandler InfoEvent;
        public event EventViewerEventHandler SuccessEvent;
        public event EventViewerEventHandler WarnEvent;
        #endregion

        #region Constructor
        /// <summary>
        /// Default Constrcutor
        /// </summary>
        public EventLog() { }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="p_EventViewerName">Event Viewer Name</param>
        public EventLog(string p_EventViewerName)
        {
            this.m_EventViewerName = p_EventViewerName;
            this.m_EventLogFmk = new System.Diagnostics.EventLog(this.m_EventViewerName);
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="p_EventViewerName">Event Viewer Name</param>
        public EventLog(string p_EventViewerName, string p_SourceName)
        {
            this.m_EventViewerName = p_EventViewerName;
            this.m_SourceName = p_SourceName;
            this.m_EventLogFmk = new System.Diagnostics.EventLog(this.m_EventViewerName);
        }
        #endregion

        #region ConfigureEventLog
        /// <summary>
        /// EventLog Configuration/ Initialisation
        /// </summary>
        private void ConfigureEventLog()
        {
            try
            {
                string text1 = @"SYSTEM\CurrentControlSet\Services\Eventlog\" + this.m_EventViewerName;
                RegistryKey key1 = Registry.LocalMachine.CreateSubKey(text1);
                object obj1 = key1.GetValue("Retention");
                if ((obj1 == null) || ((obj1 is int) && (((int)obj1) != 0)))
                {
                    key1.SetValue("Retention", 0);
                }
                obj1 = key1.GetValue("MaxSize");
                if ((obj1 == null) || ((obj1 is int) && (((int)obj1) != 0x100000)))
                {
                    key1.SetValue("MaxSize", 0x100000);
                }
                //Set Sources Key ... Very Important
                if (key1.GetValue("Sources") == null)
                {
                    key1.SetValue("Sources", this.m_SourceName);
                }
                this.m_EventlogConfigurate = true;
            }
            catch (Exception exception1)
            {
                Console.WriteLine("Error while setting event log parameter. Message : " + exception1.Message);
            }
        }
        #endregion

        #region LaunchEvent
        /// <summary>
        /// Launch Event Log Event
        /// </summary>
        /// <param name="p_Source">Source</param>
        /// <param name="p_description">Description</param>
        /// <param name="p_EventLogEntryType">Event Log Type</param>
        private void LaunchEvent(string p_Source, string p_description, EventLogEntryType p_EventLogEntryType)
        {
            switch (p_EventLogEntryType)
            {
                case EventLogEntryType.Error:
                    if (this.ErrorEvent != null)
                    {
                        this.ErrorEvent(this, new EventViewerEventArgs(p_Source, p_description));
                    }
                    return;

                case EventLogEntryType.Warning:
                    if (this.WarnEvent != null)
                    {
                        this.WarnEvent(this, new EventViewerEventArgs(p_Source, p_description));
                    }
                    return;

                case EventLogEntryType.Information:
                    if (this.InfoEvent != null)
                    {
                        this.InfoEvent(this, new EventViewerEventArgs(p_Source, p_description));
                    }
                    return;

                case EventLogEntryType.SuccessAudit:
                    if (this.SuccessEvent != null)
                    {
                        this.SuccessEvent(this, new EventViewerEventArgs(p_Source, p_description));
                    }
                    return;

                case EventLogEntryType.FailureAudit:
                    if (this.FailureEvent != null)
                    {
                        this.FailureEvent(this, new EventViewerEventArgs(p_Source, p_description));
                    }
                    return;
            }
            if (this.DebugEvent != null)
            {
                this.DebugEvent(this, new EventViewerEventArgs(p_Source, p_description));
            }
        }
        #endregion

        #region WriteIntoEventViewer
        /// <summary>
        /// Adding Entry into Event Viewer
        /// </summary>
        /// <param name="p_description">Description</param>
        /// <param name="p_EventLogEntryType">Event Log Entry</param>
        private void WriteIntoEventViewer(string p_description, EventLogEntryType p_EventLogEntryType)
        {
            if (!System.Diagnostics.EventLog.SourceExists(this.m_SourceName))
            {
                System.Diagnostics.EventLog.CreateEventSource(this.m_SourceName, this.m_EventViewerName);
            }
            this.m_EventLogFmk.Source = this.m_SourceName;
            if (!this.m_EventlogConfigurate)
            {
                this.ConfigureEventLog();
            }
            this.m_EventLogFmk.WriteEntry(p_description, p_EventLogEntryType);
            this.LaunchEvent(this.m_SourceName, p_description, p_EventLogEntryType);
        }

        private void WriteIntoEventViewer(string p_Title, string p_Information, EventLogEntryType p_EventLogEntryType)
        {
            this.WriteIntoEventViewer(p_Title + "\n" + p_Information, p_EventLogEntryType);
        }

        private void WriteIntoEventViewer(string p_Title, Exception ex, EventLogEntryType p_EventLogEntryType)
        {
            this.WriteIntoEventViewer(p_Title + "\nSource " + ex.Source + "\t" + ex.TargetSite + "\nException : \n" + ex.Message + "\nStackTrace :\n" + ex.StackTrace, p_EventLogEntryType);
        }

        private void WriteIntoEventViewer(string p_Title, string p_Information, Exception ex, EventLogEntryType p_EventLogEntryType)
        {
            this.WriteIntoEventViewer(p_Title + "\n" + p_Information + "\nSource " + ex.Source + "\t" + ex.TargetSite + "\nException : \n" + ex.Message + "\nStackTrace :\n" + ex.StackTrace, p_EventLogEntryType);
        }
        #endregion

        #region Event Log Entry Type

        #region Debug
        public virtual void Debug(string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pDescription, EventLogEntryType.Information);
            }
        }

        public virtual void Debug(string pMessageTitle, Exception ex)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, ex, EventLogEntryType.Information);
            }
        }
        public virtual void Debug(string pMessageTitle, string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, EventLogEntryType.Information);
            }
        }

        public virtual void Debug(string pMessageTitle, string pDescription, Exception ex)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, ex, EventLogEntryType.Information);
            }
        }
        #endregion

        #region Error
        public virtual void Error(string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pDescription, EventLogEntryType.Error);
            }
        }
        public virtual void Error(string pMessageTitle, Exception ex)
        {
            if (this.m_IsErrorEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, ex, EventLogEntryType.Error);
            }
        }
        public virtual void Error(string pMessageTitle, string pDescription)
        {
            if (this.m_IsErrorEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, EventLogEntryType.Error);
            }
        }

        public virtual void Error(string pMessageTitle, string pDescription, Exception ex)
        {
            if (this.m_IsErrorEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, ex, EventLogEntryType.Error);
            }
        }
        #endregion

        #region Failure
        public virtual void Failure(string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pDescription, EventLogEntryType.FailureAudit);
            }
        }

        public virtual void Failure(string pMessageTitle, Exception ex)
        {
            if (this.m_IsFailureEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, ex, EventLogEntryType.FailureAudit);
            }
        }

        public virtual void Failure(string pMessageTitle, string pDescription)
        {
            if (this.m_IsFailureEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, EventLogEntryType.FailureAudit);
            }
        }

        public virtual void Failure(string pMessageTitle, string pDescription, Exception ex)
        {
            if (this.m_IsFailureEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, ex, EventLogEntryType.FailureAudit);
            }
        }
        #endregion

        #region Info
        public virtual void Info(string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pDescription, EventLogEntryType.Information);
            }
        }

        public virtual void Info(string pMessageTitle, Exception ex)
        {
            if (this.m_IsInfoEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, ex, EventLogEntryType.Information);
            }
        }

        public virtual void Info(string pMessageTitle, string pDescription)
        {
            if (this.m_IsInfoEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, EventLogEntryType.Information);
            }
        }

        public virtual void Info(string pMessageTitle, string pDescription, Exception ex)
        {
            if (this.m_IsInfoEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, ex, EventLogEntryType.Information);
            }
        }
        #endregion

        #region Success
        public virtual void Success(string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pDescription, EventLogEntryType.SuccessAudit);
            }
        }

        public virtual void Success(string pMessageTitle, Exception ex)
        {
            if (this.m_IsSuccessEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, ex, EventLogEntryType.SuccessAudit);
            }
        }

        public virtual void Success(string pMessageTitle, string pDescription)
        {
            if (this.m_IsSuccessEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, EventLogEntryType.SuccessAudit);
            }
        }

        public virtual void Success(string pMessageTitle, string pDescription, Exception ex)
        {
            if (this.m_IsSuccessEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, ex, EventLogEntryType.SuccessAudit);
            }
        }
        #endregion

        #region Warn
        public virtual void Warn(string pDescription)
        {
            if (this.m_IsDebugEnabled)
            {
                this.WriteIntoEventViewer(pDescription, EventLogEntryType.Warning);
            }
        }

        public virtual void Warn(string pMessageTitle, Exception ex)
        {
            if (this.m_IsWarnEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, ex, EventLogEntryType.Warning);
            }
        }

        public virtual void Warn(string pMessageTitle, string pDescription)
        {
            if (this.m_IsWarnEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, EventLogEntryType.Warning);
            }
        }

        public virtual void Warn(string pMessageTitle, string pDescription, Exception ex)
        {
            if (this.m_IsWarnEnabled)
            {
                this.WriteIntoEventViewer(pMessageTitle, pDescription, ex, EventLogEntryType.Warning);
            }
        }
        #endregion

        #endregion

        #region Accessors

        public bool IsDebugEnabled
        {
            get
            {
                return this.m_IsDebugEnabled;
            }
            set
            {
                this.m_IsDebugEnabled = value;
            }
        }

        public bool IsErrorEnabled
        {
            get
            {
                return this.m_IsInfoEnabled;
            }
            set
            {
                this.m_IsInfoEnabled = value;
            }
        }

        public bool IsFailureEnabled
        {
            get
            {
                return this.m_IsFailureEnabled;
            }
            set
            {
                this.m_IsFailureEnabled = value;
            }
        }

        public bool IsInfoEnabled
        {
            get
            {
                return this.m_IsInfoEnabled;
            }
            set
            {
                this.m_IsInfoEnabled = value;
            }
        }

        public bool IsSuccessEnabled
        {
            get
            {
                return this.m_IsSuccessEnabled;
            }
            set
            {
                this.m_IsSuccessEnabled = value;
            }
        }

        public bool IsWarnEnabled
        {
            get
            {
                return this.m_IsWarnEnabled;
            }
            set
            {
                this.m_IsWarnEnabled = value;
            }
        }

        public string SourceName
        {
            set
            {
                this.m_SourceName = value;
                this.ConfigureEventLog();
            }
        }

        #endregion
    }
}